"""
统一监控模块 - 整合所有监控功能

包含系统监控、健康检查、指标收集、告警管理等功能
"""

import asyncio
import time
import json
import psutil
from typing import Dict, List, Any, Optional, Callable, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict
from collections import defaultdict, deque
from enum import Enum
from ..core import unified_logger
from ..core import event_bus, EventTypes


class HealthStatus(Enum):
    """健康状态枚举"""
    HEALTHY = "healthy"
    WARNING = "warning" 
    CRITICAL = "critical"
    UNKNOWN = "unknown"


class AlertLevel(Enum):
    """告警级别"""
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"


@dataclass
class SystemMetrics:
    """系统指标"""
    timestamp: datetime
    cpu_percent: float
    memory_percent: float
    memory_used_mb: float
    memory_available_mb: float
    disk_usage_percent: float
    network_bytes_sent: int
    network_bytes_recv: int
    active_connections: int
    process_count: int


@dataclass
class PerformanceMetrics:
    """性能指标"""
    timestamp: datetime
    component: str
    operation: str
    duration_ms: float
    success: bool
    error_message: Optional[str] = None


@dataclass
class HealthCheck:
    """健康检查结果"""
    component: str
    status: HealthStatus
    message: str
    timestamp: datetime
    details: Optional[Dict[str, Any]] = None


@dataclass
class Alert:
    """告警信息"""
    id: str
    level: AlertLevel
    title: str
    message: str
    component: str
    timestamp: datetime
    resolved: bool = False
    resolved_at: Optional[datetime] = None


class UnifiedMonitor:
    """统一监控器 - 整合所有监控功能"""
    
    def __init__(self, collection_interval: int = 30):
        self.logger = unified_logger.get_logger("unified_monitor")
        self.collection_interval = collection_interval
        self.is_monitoring = False
        self._monitoring_task = None
        
        # 数据存储
        self.system_metrics_history = deque(maxlen=1000)
        self.performance_metrics_history = deque(maxlen=5000)
        self.health_checks = {}
        self.alerts = {}
        self.alert_rules = {}
        
        # 健康检查函数
        self.health_check_functions = {}
        
        # 初始化基础告警规则
        self._setup_default_alert_rules()
    
    def _setup_default_alert_rules(self):
        """设置默认告警规则"""
        self.alert_rules = {
            'high_cpu': {
                'threshold': 80.0,
                'duration': 300,  # 5分钟
                'level': AlertLevel.WARNING
            },
            'high_memory': {
                'threshold': 85.0,
                'duration': 300,
                'level': AlertLevel.WARNING
            },
            'high_disk': {
                'threshold': 90.0,
                'duration': 60,
                'level': AlertLevel.ERROR
            }
        }
    
    async def start_monitoring(self):
        """启动监控"""
        if self.is_monitoring:
            return
            
        self.is_monitoring = True
        self._monitoring_task = asyncio.create_task(self._monitoring_loop())
        self.logger.info("统一监控已启动")
    
    async def stop_monitoring(self):
        """停止监控"""
        if not self.is_monitoring:
            return
            
        self.is_monitoring = False
        if self._monitoring_task:
            self._monitoring_task.cancel()
            try:
                await self._monitoring_task
            except asyncio.CancelledError:
                pass
        self.logger.info("统一监控已停止")
    
    async def _monitoring_loop(self):
        """监控循环"""
        while self.is_monitoring:
            try:
                # 收集系统指标
                metrics = await self.collect_system_metrics()
                self.system_metrics_history.append(metrics)
                
                # 检查告警
                await self._check_alerts(metrics)
                
                # 运行健康检查
                await self.run_all_health_checks()
                
                await asyncio.sleep(self.collection_interval)
                
            except Exception as e:
                self.logger.error(f"监控循环错误: {e}")
                await asyncio.sleep(5)
    
    async def collect_system_metrics(self) -> SystemMetrics:
        """收集系统指标"""
        try:
            # CPU使用率
            cpu_percent = psutil.cpu_percent(interval=1)
            
            # 内存信息
            memory = psutil.virtual_memory()
            
            # 磁盘使用率
            disk = psutil.disk_usage('/')
            
            # 网络信息
            network = psutil.net_io_counters()
            
            # 进程数量
            process_count = len(psutil.pids())
            
            # 网络连接数
            try:
                connections = len(psutil.net_connections())
            except (psutil.AccessDenied, OSError):
                connections = 0
            
            metrics = SystemMetrics(
                timestamp=datetime.now(),
                cpu_percent=cpu_percent,
                memory_percent=memory.percent,
                memory_used_mb=memory.used / 1024 / 1024,
                memory_available_mb=memory.available / 1024 / 1024,
                disk_usage_percent=disk.percent,
                network_bytes_sent=network.bytes_sent,
                network_bytes_recv=network.bytes_recv,
                active_connections=connections,
                process_count=process_count
            )
            
            return metrics
            
        except Exception as e:
            self.logger.error(f"收集系统指标失败: {e}")
            raise
    
    async def record_performance_metric(self, component: str, operation: str, 
                                      duration_ms: float, success: bool = True,
                                      error_message: Optional[str] = None):
        """记录性能指标"""
        metric = PerformanceMetrics(
            timestamp=datetime.now(),
            component=component,
            operation=operation,
            duration_ms=duration_ms,
            success=success,
            error_message=error_message
        )
        
        self.performance_metrics_history.append(metric)
        
        # 发送事件
        await event_bus.emit(EventTypes.PERFORMANCE_METRIC, {
            'component': component,
            'operation': operation,
            'duration_ms': duration_ms,
            'success': success
        })
    
    def register_health_check(self, component: str, check_func: Callable):
        """注册健康检查函数"""
        self.health_check_functions[component] = check_func
        self.logger.info(f"已注册健康检查: {component}")
    
    async def run_health_check(self, component: str) -> HealthCheck:
        """运行单个健康检查"""
        if component not in self.health_check_functions:
            return HealthCheck(
                component=component,
                status=HealthStatus.UNKNOWN,
                message="未找到健康检查函数",
                timestamp=datetime.now()
            )
        
        try:
            check_func = self.health_check_functions[component]
            result = await check_func() if asyncio.iscoroutinefunction(check_func) else check_func()
            
            if isinstance(result, dict):
                status = HealthStatus(result.get('status', 'unknown'))
                message = result.get('message', '')
                details = result.get('details')
            else:
                status = HealthStatus.HEALTHY if result else HealthStatus.CRITICAL
                message = "健康检查通过" if result else "健康检查失败"
                details = None
            
            health_check = HealthCheck(
                component=component,
                status=status,
                message=message,
                timestamp=datetime.now(),
                details=details
            )
            
            self.health_checks[component] = health_check
            return health_check
            
        except Exception as e:
            self.logger.error(f"健康检查失败 {component}: {e}")
            health_check = HealthCheck(
                component=component,
                status=HealthStatus.CRITICAL,
                message=f"健康检查异常: {str(e)}",
                timestamp=datetime.now()
            )
            self.health_checks[component] = health_check
            return health_check
    
    async def run_all_health_checks(self) -> Dict[str, HealthCheck]:
        """运行所有健康检查"""
        results = {}
        for component in self.health_check_functions:
            results[component] = await self.run_health_check(component)
        return results
    
    async def _check_alerts(self, metrics: SystemMetrics):
        """检查告警条件"""
        current_time = datetime.now()
        
        # 检查CPU告警
        if metrics.cpu_percent > self.alert_rules['high_cpu']['threshold']:
            await self._trigger_alert(
                'high_cpu',
                AlertLevel.WARNING,
                f"CPU使用率过高: {metrics.cpu_percent:.1f}%",
                f"当前CPU使用率为{metrics.cpu_percent:.1f}%，超过阈值{self.alert_rules['high_cpu']['threshold']}%"
            )
        
        # 检查内存告警
        if metrics.memory_percent > self.alert_rules['high_memory']['threshold']:
            await self._trigger_alert(
                'high_memory',
                AlertLevel.WARNING,
                f"内存使用率过高: {metrics.memory_percent:.1f}%",
                f"当前内存使用率为{metrics.memory_percent:.1f}%，超过阈值{self.alert_rules['high_memory']['threshold']}%"
            )
        
        # 检查磁盘告警
        if metrics.disk_usage_percent > self.alert_rules['high_disk']['threshold']:
            await self._trigger_alert(
                'high_disk',
                AlertLevel.ERROR,
                f"磁盘使用率过高: {metrics.disk_usage_percent:.1f}%",
                f"当前磁盘使用率为{metrics.disk_usage_percent:.1f}%，超过阈值{self.alert_rules['high_disk']['threshold']}%"
            )
    
    async def _trigger_alert(self, alert_id: str, level: AlertLevel, title: str, message: str):
        """触发告警"""
        if alert_id in self.alerts and not self.alerts[alert_id].resolved:
            return  # 告警已存在且未解决
        
        alert = Alert(
            id=alert_id,
            level=level,
            title=title,
            message=message,
            component="system",
            timestamp=datetime.now()
        )
        
        self.alerts[alert_id] = alert
        self.logger.warning(f"触发告警: {title} - {message}")
        
        # 发送告警事件
        await event_bus.emit(EventTypes.ALERT_TRIGGERED, {
            'alert_id': alert_id,
            'level': level.value,
            'title': title,
            'message': message
        })
    
    def get_system_summary(self, minutes: int = 5) -> Dict[str, Any]:
        """获取系统摘要"""
        cutoff_time = datetime.now() - timedelta(minutes=minutes)
        recent_metrics = [m for m in self.system_metrics_history if m.timestamp >= cutoff_time]
        
        if not recent_metrics:
            return {}
        
        return {
            'cpu': {
                'current': recent_metrics[-1].cpu_percent,
                'average': sum(m.cpu_percent for m in recent_metrics) / len(recent_metrics),
                'max': max(m.cpu_percent for m in recent_metrics)
            },
            'memory': {
                'current': recent_metrics[-1].memory_percent,
                'average': sum(m.memory_percent for m in recent_metrics) / len(recent_metrics),
                'max': max(m.memory_percent for m in recent_metrics)
            },
            'disk': {
                'current': recent_metrics[-1].disk_usage_percent
            },
            'network': {
                'bytes_sent': recent_metrics[-1].network_bytes_sent,
                'bytes_recv': recent_metrics[-1].network_bytes_recv
            }
        }
    
    def get_health_summary(self) -> Dict[str, Any]:
        """获取健康状态摘要"""
        if not self.health_checks:
            return {'overall': 'unknown', 'components': {}}
        
        status_counts = defaultdict(int)
        for check in self.health_checks.values():
            status_counts[check.status.value] += 1
        
        # 确定整体状态
        if status_counts['critical'] > 0:
            overall = 'critical'
        elif status_counts['warning'] > 0:
            overall = 'warning'
        elif status_counts['healthy'] > 0:
            overall = 'healthy'
        else:
            overall = 'unknown'
        
        return {
            'overall': overall,
            'components': {name: check.status.value for name, check in self.health_checks.items()},
            'counts': dict(status_counts)
        }
    
    def get_active_alerts(self) -> List[Dict[str, Any]]:
        """获取活跃告警"""
        return [
            asdict(alert) for alert in self.alerts.values() 
            if not alert.resolved
        ]


# 全局监控实例
unified_monitor = UnifiedMonitor()


def monitor_performance(component: str, operation: str = None):
    """性能监控装饰器"""
    def decorator(func):
        async def async_wrapper(*args, **kwargs):
            start_time = time.time()
            op_name = operation or func.__name__
            success = True
            error_msg = None
            
            try:
                result = await func(*args, **kwargs)
                return result
            except Exception as e:
                success = False
                error_msg = str(e)
                raise
            finally:
                duration = (time.time() - start_time) * 1000
                await unified_monitor.record_performance_metric(
                    component, op_name, duration, success, error_msg
                )
        
        def sync_wrapper(*args, **kwargs):
            start_time = time.time()
            op_name = operation or func.__name__
            success = True
            error_msg = None
            
            try:
                result = func(*args, **kwargs)
                return result
            except Exception as e:
                success = False
                error_msg = str(e)
                raise
            finally:
                duration = (time.time() - start_time) * 1000
                # 对于同步函数，创建异步任务记录指标
                asyncio.create_task(unified_monitor.record_performance_metric(
                    component, op_name, duration, success, error_msg
                ))
        
        return async_wrapper if asyncio.iscoroutinefunction(func) else sync_wrapper
    
    return decorator